module memory(/*AUTOARG*/
   // Outputs
   mem_o_data, mem_o_addr, mem_o_dest_reg, mem_o_ctrl,
   mem_o_line_valid, mem_o_fin_dst_reg, mem_o_fin_data,
   mem_o_fin_ctrl, mem_o_hazard, mem_o_fin_valid,
   // Inputs
   clk, reset, mem_i_data_ex, mem_i_addr_ex, mem_i_dest_reg_ex,
   mem_i_ctrl_ex, mem_i_line_valid_ex, mem_i_line, mem_i_dest_m,
   mem_i_ctrl_m, mem_i_line_valid_m
   );

input clk;
input reset;
input [31:0] mem_i_data_ex;
input [31:0] mem_i_addr_ex;
input [4:0]  mem_i_dest_reg_ex;
input [2:0] mem_i_ctrl_ex;
input [3:0] mem_i_line_valid_ex;

input [63:0] mem_i_line;
input [4:0] mem_i_dest_m;
input mem_i_ctrl_m;
input [3:0] mem_i_line_valid_m;

output [31:0] mem_o_data;
output [31:0] mem_o_addr;
output [4:0]  mem_o_dest_reg;
output [1:0] mem_o_ctrl;
output [3:0] mem_o_line_valid;

output [4:0] mem_o_fin_dst_reg;
output [31:0] mem_o_fin_data;
output mem_o_fin_ctrl;
output mem_o_hazard;
output [3:0] mem_o_fin_valid;


reg [31:0] mem_b_data;
reg [31:0] mem_b_addr;
reg [4:0] mem_b_dest_reg;
reg [1:0] mem_b_ctrl;
reg [3:0] mem_b_line_valid;

reg [4:0] mem_b_fin_dst_reg;
reg [31:0] mem_b_fin_data;
reg mem_b_fin_ctrl;
reg mem_b_hazard;
reg [3:0] mem_b_fin_valid;


wire data_i_valid;
wire data_select;

//assigning buffer value to outputs------------
assign mem_o_data = mem_b_data;
assign mem_o_addr = mem_b_addr;
assign mem_o_dest_reg = mem_b_dest_reg;
assign mem_o_ctrl = mem_b_ctrl;
assign mem_o_line_valid = mem_b_line_valid;

assign mem_o_fin_dst_reg = mem_b_fin_dst_reg;
assign mem_o_fin_data = mem_b_fin_data;
assign mem_o_fin_ctrl = mem_b_fin_ctrl;
assign mem_o_hazard = mem_b_hazard; 
assign mem_o_fin_valid = mem_b_fin_valid;


assign data_i_valid = mem_i_line_valid_m[0] | mem_i_line_valid_m[1] | mem_i_line_valid_m[2] | mem_i_line_valid_m[3];
assign data_select = mem_i_line_valid_m[0] & mem_i_line_valid_m[1] & mem_i_line_valid_m[2] & mem_i_line_valid_m[3];

//-------------sending out memory requests---------------
always @(posedge clk or negedge reset)
begin
	if(!reset)
	begin
	mem_b_line_valid <= 0;
	mem_b_fin_valid <= 0;
	end

	else
	begin
	
		if(mem_i_ctrl_ex[2] == 1)
			begin
			mem_b_data <= mem_i_data_ex;
			mem_b_addr <= mem_i_addr_ex;
			mem_b_dest_reg <= mem_i_dest_reg_ex;
			mem_b_ctrl <= mem_i_ctrl_ex[1:0];
			mem_b_line_valid <= mem_i_line_valid_ex;
			end
		
		if(data_i_valid == 1)
			begin
			mem_b_fin_dst_reg <= mem_i_dest_m;
			if(data_select == 1)
				mem_b_fin_data <= (mem_i_line[63:32] & 32'hFFFFFFFF);//logic for valid data
			else
				mem_b_fin_data <= (mem_i_line[63:32] & 32'h000000FF);
			mem_b_fin_ctrl <= mem_i_ctrl_m;
			mem_b_fin_valid <= mem_i_line_valid_m;
			mem_b_hazard <= data_i_valid;
			end
		else
			begin
			mem_b_fin_dst_reg <= 0;
			mem_b_fin_data <= 0;
			mem_b_fin_ctrl <= 0;
			mem_b_fin_valid <= 0;
			mem_b_hazard <= 0;
			
			end
	end
end



endmodule

